// Copyright (C) 2022 Linlexiao
#ifndef LOGIC_PAI_H_
#define LOGIC_PAI_H_

#include <QVector>

// 对于风的定义（只用于State的构造函数中）
enum Wind { EAST, SOUTH, WEST, NORTH, EMPTY_WIND };

// 牌的类型
enum PaiType { SUO, PIN, MAN, ZI };
// 面子的类型
enum BlockType { SEQUENCE, TRIPLET, QUAD };
// 听牌类型
enum MachiType { LIANG_MIAN, KAN_ZHANG, BIAN_ZHANG, SHUANG_PENG, DAN_QI };
enum HandFlag {
    NOMI = 0,
    FIELD_EAST = 1 << 0,
    FIELD_SOUTH = 1 << 1,
    FIELD_WEST = 1 << 2,
    FIELD_NORTH = 1 << 3,
    SEAT_EAST = 1 << 4,
    SEAT_SOUTH = 1 << 5,
    SEAT_WEST = 1 << 6,
    SEAT_NORTH = 1 << 7,
    HAITEI_RAOYUE = 1 << 8,
    HOUTEI_RAOYUI = 1 << 9,
    TENHOU = 1 << 10,
    CHIIHOU = 1 << 11,
    RINNSHANN_KAIHOU = 1 << 12,
    CHANKAN = 1 << 13,
    RIICHI = 1 << 14,
    DOUBLE_RIICHI = 1 << 15,
    IPPATSU = 1 << 16,
    TSUMO = 1 << 17,
    RON = 1 << 18,
    MENZEN = 1 << 19
};
Q_DECLARE_FLAGS(HandFlags, HandFlag)
Q_DECLARE_OPERATORS_FOR_FLAGS(HandFlags)

// 牌
class Pai {
 public:
    PaiType type;
    int num;
    bool isRed;  // 是否是赤宝牌

    bool isAgari;  // 是否是和了牌，用来决定听牌方式
    Pai(PaiType _type, int _num, bool _isRed);
    explicit Pai(const QString& s);  // 从字符构建
    QString toString();
    bool isYao();  //是否是幺九牌
    bool isRyu();  //是否是绿牌（绿一色）
    int isYakuhai(HandFlags flag);  //是否是役牌 (不是：0，普通：1，连风：2)
    bool operator==(const Pai& rhs) const;
    bool operator<(const Pai& rhs) const;
    Pai next();
    Pai() = default;

    static QVector<Pai> fromStrings(const QString& str);
};

// 面子 (顺子用开始的数字表示 如：123s -> {Sequnce,Suo,1})
class Block {
 public:
    BlockType blockType;
    PaiType paiType;
    int num;
    bool isOpen;   // 1为非门清面子（吃、碰、明杠） 0为门清面子（手中，暗杠）
    int redCount;  // 面子中赤宝牌数量
    Block(BlockType _blockType, PaiType _paiType, int _num, bool _isOpen,
          int _redCount);

    bool consistYao();  //是否含有幺九牌
    int consistYakuhai(
        HandFlags flag);  //是否是役牌刻子/杠子 (不是：0，普通：1，连风：2)
    bool operator==(const Block& rhs) const;
    static Block fromPais(QVector<Pai> pais, bool _isOpen);
    QVector<Pai> getPai();
    Block() = default;
};

class Pair {
 public:
    PaiType paiType;
    int num;
    int redCount;
    Pair(PaiType _paiType, int _num, int _redCount);
    QVector<Pai> getPai();
    bool consistYao();
    Pair() = default;
};

// 计算后手牌(除去国士无双+七对子)
class HandSet {
 public:
    QVector<Block> blocks;   //四个面子
    Pair pair;               //雀头
    QVector<Pai> dora, ura;  //宝牌指示牌，里宝牌指示牌
    Pai agariPai{};
    MachiType type;  //听牌类型
    HandFlags flag;  //场况
    HandSet(QVector<Block> _blocks, Pair _pair, QVector<Pai> _dora,
            QVector<Pai> _ura, MachiType _type, HandFlags _flag, Pai _agariPai);
    HandSet() = default;
};

class State {
 public:
    HandFlags flag;  //场风，自风，偶然役(立直，一发)自摸/荣和，是否门清
    QVector<Pai> pais;
    QVector<Pai> dora, ura;
    QVector<Block> furu;  //副露 包括暗杠
    Pai agariPai;         //和了牌

    State(Wind field, Wind seat, const QVector<HandFlag>& yakus, HandFlag agariWay,
          QVector<Pai> p, QVector<Block> _furu, QVector<Pai> d, QVector<Pai> u,
          Pai _agariPai);
};

#endif  // LOGIC_PAI_H_
